#include <EEPROM.h>
#include <SPI.h>
#include "EmonLib.h"             // Include Emon Library
#include <Tone.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>


EnergyMonitor emon1;             // Create an instance

int status;
int doorbellcount = 0;
int buttonState = 0;
int DBelladdr = 0;

boolean sendtype = false;

int SongCount = 0;
Tone tone1;
#define OCTAVE_OFFSET 0
int notes[] = { 
  0,
  NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4,
  NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B5,
  NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6,
  NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7
};
char *song = "The Simpsons:d=4,o=5,b=160:c.6,e6,f#6,8a6,g.6,e6,c6,8a,8f#,8f#,8f#,2g,8p,8p,8f#,8f#,8f#,8g,a#.,8c6,8c6,8c6,c6";
#define DBellSND 5
#define DBellBTN 4
#define DBellLED 3

#define SensorPin1      0
int rawData1;  // variables for sensor1 data
int rawData2;  // variables for sensor1 data

struct Timing {
  unsigned long current;
  unsigned long previous;
  unsigned long serial;
  unsigned long sendpower;
  unsigned long sendclock;  
  unsigned long sendcontroller;
  unsigned long sendled;    
  int delta;
} 
time = { 
  0, 0, 0, 0, 0, 0, 0, 0};

const int chipSelect = 4;

void setup()
{  
  doorbellcount = EEPROM.read(DBelladdr);
  pinMode(DBellSND, OUTPUT);
  pinMode(DBellBTN, INPUT);
  pinMode(DBellLED, OUTPUT);
  digitalWrite(DBellLED, HIGH);
  tone1.begin(DBellSND);  


  Serial.begin(115200);
  //  emon1.voltage(1, 238.5, 1.7);  // Voltage: input pin, calibration, phase_shift
  emon1.voltage(1, 138.5, 1.7);  // Voltage: input pin, calibration, phase_shift
  emon1.current(0, 85.8);       // Current: input pin, calibration.
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  Mirf.setRADDR((byte *)"power");
  Mirf.channel = 90;
  Mirf.config();
}
boolean lastbuttonstate = LOW;

void transmit(String MSG){
  if(!Mirf.isSending()){
//    Mirf.powerUpTx();
    String MSG2 ="*";
    MSG2 += MSG;
    MSG2 +="#";
    int sections = MSG2.length() / 32;
    // Serial.println(sections);
    int c =0;
    for(int i =0;i<sections +1;i++){
      Serial.println(i);
      String tmp = MSG2.substring(i*32,(i+1)*32);
      char sendmsg[tmp.length()+1];
      tmp.toCharArray(sendmsg,tmp.length() +1);
      Serial.println(sendmsg);
      Mirf.send((byte *)&sendmsg);
long startsend = millis();
  while(Mirf.isSending()){
    if (millis() - startsend > 5000){break;}
    delay(10);
    }
//    Mirf.powerDown();
    } 
  }
}
void loop()
{

  time.current = millis();
  time.delta = (int) (time.current - time.previous);
  time.previous = time.current;

  buttonState = digitalRead(DBellBTN);
  if (buttonState == HIGH) 
  {
    if (lastbuttonstate != buttonState){
      lastbuttonstate = HIGH;
      Serial.println("DoorBell Pressed");
      digitalWrite(DBellLED, LOW);
      play_rtttl(song);
      digitalWrite(DBellLED, HIGH);
      doorbellcount ++;
      EEPROM.write(DBelladdr, doorbellcount);

      Mirf.setTADDR((byte *)"clock");
      transmit("DoorBell");
//      Mirf.setTADDR((byte *)"led");
//      transmit("DoorBell");
    }
  }
  else{
    lastbuttonstate = LOW; 
  }
  emon1.calcVI(20,2000);         // Calculate all. No.of wavelengths, time-out
  rawData1 = emon1.apparentPower;
  rawData2 = emon1.Vrms;


  Serial.println(rawData1);	// Smoothed Watts
  Serial.println(rawData2);	// Smoothed Volts

  if(time.current > (time.sendclock + 10000)) { // 5 mins
if(sendtype){
  if(!Mirf.isSending()){
    Serial.println("Sending Clock");
//        Mirf.powerUpTx();
    Mirf.setTADDR((byte *)"clock");
    String MSG3 ="*";
    MSG3 += (String)rawData1;
    MSG3 += "W";
    MSG3 +="#";
    char sendmsg[MSG3.length()+1];
    MSG3.toCharArray(sendmsg,MSG3.length() +1);
    Serial.println(sendmsg);
    Mirf.send((byte *)sendmsg);
    while(Mirf.isSending()){
      delay(100);
    }

  }
sendtype = !sendtype;
}else{
   if(!Mirf.isSending()){
    Serial.println("Sending Controller");
//        Mirf.powerUpTx();
    Mirf.setTADDR((byte *)"controller");
    String MSG3 ="*";
    MSG3 += "power,";
    MSG3 += (String)rawData1;
    MSG3 += ",";
    MSG3 += (String)rawData2;  
    MSG3 += ",";
    MSG3 += (String)doorbellcount;
    MSG3 += ",";
    MSG3 +="#";
    char sendmsg[MSG3.length()+1];
    MSG3.toCharArray(sendmsg,MSG3.length() +1);
    Serial.println(sendmsg);
    Mirf.send((byte *)sendmsg);
    while(Mirf.isSending()){
      delay(100);
    }
 
}
sendtype = !sendtype;
}
    time.sendclock = time.current;
  }
  //if(time.current > (time.sendled + 13000)) { // 5 mins
  //Serial.println("Sending LED");
  //  String MSG2 ="*";
  //  MSG2 += (String)rawData1;
  //  MSG2 +="W#";
  //  Mirf.setTADDR((byte *)"led");
  //  transmit(MSG2);
  //  time.sendled = time.current;
  //}

  if(time.current > (time.sendcontroller + 16000)) { // 5 mins

//    Mirf.powerDown();
  
    time.sendcontroller = time.current;
  }  

}

#define isdigit(n) (n >= '0' && n <= '9')

void play_rtttl(char *p)
{
  // Absolutely no error checking in here
  delay(10);
  byte default_dur = 4;
  byte default_oct = 6;
  int bpm = 63;
  int num;
  long wholenote;
  long duration;
  byte note;
  byte scale;

  // format: d=N,o=N,b=NNN:
  // find the start (skip name, etc)


  while(*p != ':') p++;    // ignore name
  p++;                     // skip ':'

  // get default duration
  if(*p == 'd')
  {
    p++; 
    p++;              // skip "d="
    num = 0;
    while(isdigit(*p))
    {
      num = (num * 10) + (*p++ - '0');
    }
    if(num > 0) default_dur = num;
    p++;                   // skip comma
  }

  Serial.print("ddur: "); 
  Serial.println(default_dur, 10);

  // get default octave
  if(*p == 'o')
  {
    p++; 
    p++;              // skip "o="
    num = *p++ - '0';
    if(num >= 3 && num <=7) default_oct = num;
    p++;                   // skip comma
  }

  Serial.print("doct: "); 
  Serial.println(default_oct, 10);

  // get BPM
  if(*p == 'b')
  {
    p++; 
    p++;              // skip "b="
    num = 0;
    while(isdigit(*p))
    {
      num = (num * 10) + (*p++ - '0');
    }
    bpm = num;
    p++;                   // skip colon
  }

  Serial.print("bpm: "); 
  Serial.println(bpm, 10);

  // BPM usually expresses the number of quarter notes per minute
  wholenote = (60 * 1000L / bpm) * 4;  // this is the time for whole note (in milliseconds)

  Serial.print("wn: "); 
  Serial.println(wholenote, 10);


  // now begin note loop
  while(*p)
  {
    // first, get note duration, if available
    num = 0;
    while(isdigit(*p))
    {
      num = (num * 10) + (*p++ - '0');
    }

    if(num) duration = wholenote / num;
    else duration = wholenote / default_dur;  // we will need to check if we are a dotted note after

      // now get the note
    note = 0;

    switch(*p)
    {
    case 'c':
      note = 1;
      break;
    case 'd':
      note = 3;
      break;
    case 'e':
      note = 5;
      break;
    case 'f':
      note = 6;
      break;
    case 'g':
      note = 8;
      break;
    case 'a':
      note = 10;
      break;
    case 'b':
      note = 12;
      break;
    case 'p':
    default:
      note = 0;
    }
    p++;

    // now, get optional '#' sharp
    if(*p == '#')
    {
      note++;
      p++;
    }

    // now, get optional '.' dotted note
    if(*p == '.')
    {
      duration += duration/2;
      p++;
    }

    // now, get scale
    if(isdigit(*p))
    {
      scale = *p - '0';
      p++;
    }
    else
    {
      scale = default_oct;
    }

    scale += OCTAVE_OFFSET;

    if(*p == ',')
      p++;       // skip comma for next note (or we may be at the end)

    // now play the note

    if(note)
    {
      Serial.print("Playing: ");
      Serial.print(scale, 10); 
      Serial.print(' ');
      Serial.print(note, 10); 
      Serial.print(" (");
      Serial.print(notes[(scale - 4) * 12 + note], 10);
      Serial.print(") ");
      Serial.println(duration, 10);
      tone1.play(notes[(scale - 4) * 12 + note]);
      delay(duration);
      tone1.stop();
    }
    else
    {
      Serial.print("Pausing: ");
      Serial.println(duration, 10);
      delay(duration);
    }
  }
  Serial.println("Done Playing");
}








